---
type: tutorial
title: 初めてのスクリプトをブラウザに送信する
description: >-
  「初めてのAstroブログ」チュートリアル -
  Astroスクリプトタグを使用して、モバイルでのナビゲーションにクライアントサイドのインタラクションを追加する
i18nReady: true
---
import Badge from '~/components/Badge.astro';
import Blanks from '~/components/tutorial/Blanks.astro';
import Box from '~/components/tutorial/Box.astro';
import Checklist from '~/components/Checklist.astro';
import MultipleChoice from '~/components/tutorial/MultipleChoice.astro';
import Option from '~/components/tutorial/Option.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import { Steps } from '@astrojs/starlight/components';

クライアントサイドのインタラクションを必要とするような、モバイルの画面サイズでリンクを開閉するハンバーガーメニューを追加しましょう！

<PreCheck>
  - ハンバーガーメニューコンポーネントを作成する
  - サイト訪問者がナビゲーションメニューを開閉できるように`<script>`を書く
  - JavaScriptを`.js`ファイルに移動する
</PreCheck>

## ハンバーガーコンポーネントを作成する

モバイルメニューを開閉する`<Hamburger />`コンポーネントを作成します。

<Steps>
1. `src/components/`に`Hamburger.astro`という名前のファイルを作成します。


2. 以下のコードをコンポーネントにコピーします。これは、モバイルでナビゲーションリンクを開閉する3行の「ハンバーガー」メニューを表わします。（あとで`global.css`に新しいCSSスタイルを追加します。）

    ```astro title="src/components/Hamburger.astro"
    --- 
    ---
    <div class="hamburger">
      <span class="line"></span>
      <span class="line"></span>
      <span class="line"></span>
    </div>
    ```

3. `Header.astro`の`<Navigation />`コンポーネントの直前に、新しい`<Hamburger />`コンポーネントを配置します。

    <details>
    <summary>コードを表示</summary>

    ```astro title="src/components/Header.astro" ins={2,7}
    ---
    import Hamburger from './Hamburger.astro';
    import Navigation from './Navigation.astro';
    ---
    <header>
      <nav>
        <Hamburger />
        <Navigation />
      </nav>
    </header>
    ```
    </details>

4. 以下のハンバーガーコンポーネント用スタイルを追加します。

    ```css title="src/styles/global.css" ins={2-13, 56-58}
    /* ナビゲーションのスタイル */
    .hamburger {
      padding-right: 20px;
      cursor: pointer;
    }

    .hamburger .line {
      display: block;
      width: 40px;
      height: 5px;
      margin-bottom: 10px;
      background-color: #ff9776;
    }

    .nav-links {
      width: 100%;
      top: 5rem;
      left: 48px;
      background-color: #ff9776;
      display: none;
      margin: 0;
    }

    .nav-links a {
      display: block;
      text-align: center;
      padding: 10px 0;
      text-decoration: none;
      font-size: 1.2rem;
      font-weight: bold;
      text-transform: uppercase;
    }

    .nav-links a:hover, a:focus {
      background-color: #ff9776;
    }

    .expanded {
      display: unset;
    }

    @media screen and (min-width: 636px) {
      .nav-links {
        margin-left: 5em;
        display: block;
        position: static;
        width: auto;
        background: none;
      }

      .nav-links a {
        display: inline-block;
        padding: 15px 20px;
      }

      .hamburger {
        display: none;
      }
    }
    ```
</Steps>

## 初めてのスクリプトタグを書く

ヘッダーはまだ**インタラクティブ**ではありません。ハンバーガーメニューへのクリックに応じてナビゲーションリンクを表示したり非表示にしたりするように、ユーザーの入力に応答することができないからです。

`<script>`タグを追加すると、クライアントサイドのJavaScriptがユーザーのイベントを「待ち受け（Listen）」、それに応答します。

<Steps>
1. `index.astro`の`</body>`閉じタグの直前に、以下の`<script>`タグを追加します。

    ```astro title="src/pages/index.astro" ins={2-6}
      <Footer />
      <script>
        document.querySelector('.hamburger').addEventListener('click', () => {
          document.querySelector('.nav-links').classList.toggle('expanded');
        });
      </script>
    </body>
    ```

2. ブラウザのプレビューを複数のサイズで開き、このページのナビゲーションメニューがスクリーンサイズに対してレスポンシブであり、またユーザーの入力に反応することを確認します。
</Steps>

### `.js`ファイルをインポートする

各ページにJavaScriptを直接書く代わりに、`<script>`タグの内容をプロジェクト内の`.js`ファイルに移動しましょう。

<Steps>
1. （新しく`/scripts/`フォルダを作成した上で）`src/scripts/menu.js`を作成し、JavaScriptをそこに移動します。

    ```js title="src/scripts/menu.js"
    document.querySelector('.hamburger').addEventListener('click', () => {
      document.querySelector('.nav-links').classList.toggle('expanded');
    });
    ```

2. `index.astro`の`<script>`タグの内容を以下のファイルインポートに置き換えます。

    ```astro title="src/pages/index.astro" ins={7} del={3-5}
      <Footer />
      <script>
        document.querySelector('.hamburger').addEventListener('click', () => {
          document.querySelector('.nav-links').classList.toggle('expanded');
        });

        import "../scripts/menu.js";
      </script>
    </body>
    ```

3. ブラウザのプレビューを再度小さいサイズで開き、ハンバーガーメニューがナビゲーションリンクを開閉することを確認します。


4. 他の`about.astro`と`blog.astro`の2ページにも同じ`<script>`とインポートを追加し、両ページにレスポンシブでインタラクティブなヘッダーがあることを確認します。

    ```astro title="src/pages/about.astro & src/pages/blog.astro" ins={2-4}
      <Footer />
      <script>
        import "../scripts/menu.js";
      </script>
    </body>
    ```
</Steps>

:::note[要点]
これまでにも、サイトの一部を作成するためにJavaScriptを使用してきました。

- ページタイトルと見出しの動的な定義
- 概要ページでのスキルリストのマッピング
- HTML要素の条件に応じた表示

これらの命令はすべてビルド時に実行され、サイトの静的HTMLを作成したあと、コードは「捨てられます」。

**`<script>`タグ内のJavaScriptはブラウザに送信され**、ユーザーの操作に応じてページの更新や入力の切り替えなどを実行します。
:::



<Box icon="question-mark">

### 確認テスト

1. Astroは、コンポーネントのフロントマターに書かれたJavaScriptをいつ実行しますか？
    <MultipleChoice>
      <Option>
        AstroはJavaScriptを実行しない。
      </Option>
      <Option isCorrect>
        ビルド時。
      </Option>
      <Option>
          サイト訪問者がボタンをクリックしたとき。
      </Option>
    </MultipleChoice>

2. Astroでは任意でJavaScriptをブラウザに送信できますが、その目的は何ですか？
    <MultipleChoice>
      <Option>
        ユーザーがページリンクをクリックできるようにするため。
      </Option>
      <Option>
        読み込み時間を短縮するため。
      </Option>
      <Option isCorrect>
        クライアントサイドのインタラクティブ機能。
      </Option>
    </MultipleChoice>

3. クライアントサイドのJavaScriptがユーザーのブラウザに送信されるのは、それがどこに書かれた・インポートされたときですか？
    <MultipleChoice>
      <Option isCorrect>
        `<script>`タグ内。
      </Option>
      <Option>
        `.astro`ファイルのコードフェンスの間。
      </Option>
      <Option>
        `global.css`内。
      </Option>
    </MultipleChoice>

</Box>

<Box icon="check-list">

## チェックリスト

<Checklist>
- [ ] `<script>`タグ内のJavaScriptによりクライアントサイドのインタラクティブ機能を追加できる。
- [ ] `<script>`タグ内に`.js`ファイルをインポートできる。
</Checklist>

</Box>

### 参考

[Astroにおけるクライアントサイドスクリプト](/ja/guides/client-side-scripts/)
